package com.ts.ischool.ui.ctrl;

import java.io.InputStreamReader;
import java.text.*;
import java.util.*;
import java.util.Calendar;

import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.zkoss.calendar.*;
import org.zkoss.calendar.api.CalendarEvent;
import org.zkoss.calendar.event.CalendarsEvent;
import org.zkoss.calendar.impl.*;
import org.zkoss.util.Locales;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.Page;
import org.zkoss.zk.ui.WebApps;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.ForwardEvent;
import org.zkoss.zk.ui.metainfo.ComponentInfo;
import org.zkoss.zk.ui.select.annotation.Listen;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zul.*;
import org.zkoss.zul.Timer;

import com.ts.ischool.pojo.CalendarBean;
import com.ts.ischool.pojo.UserBean;
import com.ts.ischool.service.CalendarService;
import com.ts.ischool.utils.DateUtils;

public class CalendarController extends GenericForwardComposer<Component> {
	
	private static final long serialVersionUID = 201011240904L;
	private boolean hasPE;
	private SimpleCalendarModel cm;
	private Calendars calendars;
	private Chart mychart;
	private Popup updateMsg;
	private	Label popupLabel;
	private	Label label;
	private Timer timer;
	private Span FDOW;
	
	private Window createEvent;
	private Datebox createEvent$ppbegin;
	private Datebox createEvent$ppend;
	private Listbox createEvent$ppbt;
	private Listbox createEvent$ppet;
	private Checkbox createEvent$ppallDay;
	private Checkbox createEvent$pplocked;
	private Combobox createEvent$ppcolor;
	private Textbox createEvent$ppcnt;
	
	private Window editEvent;
	private Datebox editEvent$ppbegin;
	private Datebox editEvent$ppend;
	private Listbox editEvent$ppbt;
	private Listbox editEvent$ppet;
	private Checkbox editEvent$ppallDay;
	private Checkbox editEvent$pplocked;
	private Combobox editEvent$ppcolor;
	private Textbox editEvent$ppcnt;
	
	private static ApplicationContext context = new ClassPathXmlApplicationContext("classpath*:spring/*.xml");
	private CalendarService calendarService = (CalendarService) context.getBean("calendarService");
	
	private static final String GOOGLECALENDARURL = "https://www.googleapis.com/calendar/v3/calendars/#user/events?access_token=#password";
	private static final String CALENDAR_DELETE = "https://www.googleapis.com/calendar/v3/calendars/#user/events/#eventId";
	private static final String CALENDAR_INSERT = "https://www.googleapis.com/calendar/v3/calendars/#user/events";
	private static final String CALENDAR_UPDATE = "https://www.googleapis.com/calendar/v3/calendars/#user/events/#eventId";
	
	//@Override
	public ComponentInfo doBeforeCompose(Page page, Component parent,
			ComponentInfo compInfo) {
		initTimeDropdown(page);
		// prepare model data
		initCalendarModel(page);
		hasPE = WebApps.getFeature("pe");
		page.setAttribute("hasPE", new Boolean(hasPE));
		return super.doBeforeCompose(page, parent, compInfo);
	}
	
	//@Override
	public void doAfterCompose(Component comp) throws Exception {
		super.doAfterCompose(comp);
		syncModel();
		updateDateLabel();
		FDOW.setVisible("month".equals(calendars.getMold()) || calendars.getDays() == 7);
		queryCalendarData();
	}

	private void updateDateLabel() {
		Date b = calendars.getBeginDate();
		Date e = calendars.getEndDate();
		SimpleDateFormat sdfV = new SimpleDateFormat(
				"yyyy/MMM/dd", Locales.getCurrent());
		sdfV.setTimeZone(calendars.getDefaultTimeZone());
		label.setValue(sdfV.format(b) + " - " + sdfV.format(e));
	}

	private void initTimeDropdown(Page page) {
		List dateTime = new LinkedList();
		
		Calendar calendar = Calendar.getInstance();
		SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		
		for (int i = 0; i < 288; i++) {
			dateTime.add(sdf.format(calendar.getTime()));
			calendar.add(Calendar.MINUTE, 5);
		}
		page.setAttribute("dateTime", dateTime);
	}
	
	private void initCalendarModel(Page page) {
		UserBean user = (UserBean) Executions.getCurrent().getSession().getAttribute("loginUserInfo");
		try {
			List<CalendarBean> listgoogle = queryGoogleCalendarData(user);
			List<CalendarBean> list = calendarService.findCalendarsByUserId(user.getId());
			if (list != null && list.size() > 0) {
				list.removeAll(listgoogle);
				String[] ids = new String[list.size()];
				for (int i = 0; i < list.size(); i++) {
					CalendarBean c = list.get(i);
					ids[i] = c.getId().toString();
				}
				if (list != null && list.size() > 0) {
					calendarService.deleteCalendarBatch(ids);
				}
			}
			String[] str = new String[listgoogle.size()];
			if (listgoogle != null && listgoogle.size() > 0) {
				for (int i = 0; i < listgoogle.size(); i++) {
					CalendarBean c = listgoogle.get(i);
					str[i] = c.getGoogleId();
				}
				List<CalendarBean> tmpList = calendarService.findCalendarsByIds(str);
				calendarService.updateCalendarBatch(tmpList);
				listgoogle.removeAll(tmpList);
			}
			calendarService.addCalendarBatch(listgoogle);
				
			// fill the events' data
			cm = new SimpleCalendarModel();
			page.setAttribute("cm", cm);
		} catch(Exception e) {
			
		}
	}

	private void syncModel() {
		if (!hasPE) return;
		List list = cm.get(calendars.getBeginDate(), calendars.getEndDate(), null);
		double red = 0, blue = 0, green = 0, purple = 0, khaki = 0;
		int size = list.size();
		for (Iterator it = list.iterator(); it.hasNext();) {
			String color = ((CalendarEvent)it.next()).getContentColor();
			if ("#D96666".equals(color))
				red += 1;
			else if ("#668CD9".equals(color))
				blue += 1;
			else if ("#4CB052".equals(color))
				green += 1;
			else if ("#B373B3".equals(color))
				purple += 1;
			else
				khaki += 1;
		}
		 PieModel model = new SimplePieModel();
		 model.setValue("Red Events", new Double(size > 0 ? (red/size)*100 : 0));
		 model.setValue("Blue Events", new Double(size > 0 ? (blue/size)*100 : 0));
		 model.setValue("Green Events", new Double(size > 0 ? (green/size)*100: 0));
		 model.setValue("Khaki Events", new Double(size > 0 ? (khaki/size)*100: 0));
		 model.setValue("Purple Events", new Double(size > 0 ? (purple/size)*100 : 0));
		 mychart.setModel(model);
		 mychart.invalidate();
	}
	
	public void onEventCreate$calendars(ForwardEvent event) {
		CalendarsEvent evt = (CalendarsEvent) event.getOrigin();
		int left = evt.getX();
		int top = evt.getY();
		int timeslots = calendars.getTimeslots();
		int timeslotTime = 60 / timeslots;
		if (top + 245 > evt.getDesktopHeight())
			top = evt.getDesktopHeight() - 245;
		if (left + 410 > evt.getDesktopWidth())
			left = evt.getDesktopWidth() - 410;
		createEvent.setLeft(left + "px");
		createEvent.setTop(top + "px");
		SimpleDateFormat create_sdf = new SimpleDateFormat("HH:mm");
		create_sdf.setTimeZone(calendars.getDefaultTimeZone());
		String[] times = create_sdf.format(evt.getBeginDate()).split(":");
		int hours = Integer.parseInt(times[0]) * timeslots;
		int mins = Integer.parseInt(times[1]);
		int bdTimeSum = hours + mins;
		hours += mins / timeslotTime;
		
		createEvent$ppbt.setSelectedIndex(hours * 12 / timeslots);
		times = create_sdf.format(evt.getEndDate()).split(":");
		hours = Integer.parseInt(times[0]) * timeslots;
		mins = Integer.parseInt(times[1]);
		int edTimeSum = hours + mins;
		hours += mins / timeslotTime;
		((Listbox)createEvent.getFellow("ppet")).setSelectedIndex(hours * 12 / timeslots);
		boolean isAllday = (bdTimeSum + edTimeSum) == 0;
		
		createEvent$ppbegin.setTimeZone(calendars.getDefaultTimeZone());
		createEvent$ppbegin.setValue(evt.getBeginDate());
		createEvent$ppend.setTimeZone(calendars.getDefaultTimeZone());
		createEvent$ppend.setValue(evt.getEndDate());
		createEvent$ppallDay.setChecked(isAllday);
		createEvent$pplocked.setChecked(false);
		createEvent$ppbt.setVisible(!isAllday);
		createEvent$ppet.setVisible(!isAllday);

		createEvent.setVisible(true);
		createEvent.setAttribute("calevent", evt);
		evt.stopClearGhost();
	}
	
	public void onClose$createEvent(ForwardEvent event) {
		event.getOrigin().stopPropagation();
		((CalendarsEvent)createEvent.getAttribute("calevent")).clearGhost();
		createEvent.setVisible(false);
	}
	
	public void onClick$okBtn$createEvent(ForwardEvent event) throws Exception {
		SimpleCalendarEvent ce = new SimpleCalendarEvent();
		Calendar cal = Calendar.getInstance(calendars.getDefaultTimeZone());
		Date beginDate = createEvent$ppbegin.getValue();
		Date endDate = createEvent$ppend.getValue();
		
		int bmin = 0;
		int emin = 0;
		if (!createEvent$ppallDay.isChecked()) {
			String[] times = createEvent$ppbt.getSelectedItem().getLabel().split(":");
			
			cal.setTime(beginDate);
			cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(times[0]));
			cal.set(Calendar.MINUTE, Integer.parseInt(times[1]));
			cal.set(Calendar.SECOND, 0);
			cal.set(Calendar.MILLISECOND, 0);
			beginDate = cal.getTime();
			bmin = cal.get(Calendar.MINUTE);
			times = createEvent$ppet.getSelectedItem().getLabel().split(":");
			cal.setTime(endDate);
			cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(times[0]));
			cal.set(Calendar.MINUTE, Integer.parseInt(times[1]));
			cal.set(Calendar.SECOND, 0);
			cal.set(Calendar.MILLISECOND, 0);
			endDate = cal.getTime();
			emin = cal.get(Calendar.MINUTE);
			
			if (!beginDate.before(endDate)) {
				createEvent.setVisible(false);
				alert("The end date cannot be earlier than or equal to begin date!");
				((CalendarsEvent)createEvent.getAttribute("calevent")).clearGhost();
				return;
			}
			if (bmin == 5 || bmin == 25 || bmin == 35 || bmin == 55) {
				createEvent.setVisible(false);
				alert("The begin minute:" + bmin + ", is not supported");
				((CalendarsEvent)createEvent.getAttribute("calevent")).clearGhost();
				return;
			}
			if (emin == 5 || emin == 25 || emin == 35 || emin == 55) {
				createEvent.setVisible(false);
				alert("The end minute:" + emin + ", doesn't support");
				((CalendarsEvent)createEvent.getAttribute("calevent")).clearGhost();
				return;
			}			
		}else{
			cal.setTime(beginDate);
			cal.set(Calendar.HOUR_OF_DAY, 0);
			cal.set(Calendar.MINUTE, 0);
			cal.set(Calendar.SECOND, 0);
			cal.set(Calendar.MILLISECOND, 0);
			beginDate = cal.getTime();
			bmin = cal.get(Calendar.MINUTE);

			cal.setTime(endDate);
			cal.set(Calendar.HOUR_OF_DAY, 0);
			cal.set(Calendar.MINUTE, 0);
			cal.set(Calendar.SECOND, 0);
			cal.set(Calendar.MILLISECOND, 0);
			endDate = cal.getTime();
			emin = cal.get(Calendar.MINUTE);
			
			if(endDate.equals(beginDate)){
				cal.set(Calendar.HOUR_OF_DAY, 24);
				endDate = cal.getTime();
				emin = cal.get(Calendar.MINUTE);
			}
		}
		
		String[] colors = ((String)createEvent$ppcolor.getSelectedItem().getValue()).split(",");
		ce.setHeaderColor(colors[0]);
		ce.setContentColor(colors[1]);
		ce.setBeginDate(beginDate);
		ce.setEndDate(endDate);
		ce.setContent(createEvent$ppcnt.getValue());
		ce.setLocked(createEvent$pplocked.isChecked());
		
		UserBean user = (UserBean) Executions.getCurrent().getSession().getAttribute("loginUserInfo");
		HttpClient httpclient = new DefaultHttpClient();
		String url = CALENDAR_INSERT.replace("#user", user.getLoginName());
		HttpPost httpost = new HttpPost(url);
		httpost.addHeader("Content-Type", "application/json");
		httpost.addHeader("Authorization", "Bearer "+user.getPassword()+"");
		TimeZone zone = calendars.getDefaultTimeZone();
		JSONObject object = new JSONObject("{\"end\": {\"dateTime\": \""+DateUtils.getFormateDateStr(ce.getEndDate(), "yyyy-MM-dd'T'HH:mm:ss")+"\", \"timeZone\": \""+zone.getID()+"\"},\"start\": {\"dateTime\": \""+DateUtils.getFormateDateStr(ce.getBeginDate(), "yyyy-MM-dd'T'HH:mm:ss")+"\", \"timeZone\": \""+zone.getID()+"\"}}");
		String color = null;
		if ("#668CD9".equals(colors[1]))
			color = "9";
		else if ("#D96666".equals(colors[1]))
			color = "11";
		else if ("#4CB052".equals(colors[1]))
			color = "10";
		else if ("#B373B3".equals(colors[1]))
			color = "3";
		else
			color = "5";
		object.append("colorId", color);
		object.append("summary", ce.getContent());
		StringEntity myEntity = new StringEntity(object.toString());
		httpost.setEntity(myEntity);
		HttpResponse response = httpclient.execute(httpost);
		HttpEntity resEntity = response.getEntity();
		InputStreamReader reader = new InputStreamReader(
				resEntity.getContent(), "UTF-8");
		char[] buff = new char[1024];
		StringBuffer sb = new StringBuffer();
		int length = 0;
		while ((length = reader.read(buff)) != -1) {
			sb.append(new String(buff, 0, length));
		}
		JSONObject jsonobject = new JSONObject(sb.toString());
		String googleId = null;
		if (jsonobject.has("id"))
			googleId = jsonobject.get("id").toString();
		
		CalendarBean c = new CalendarBean();
		c.setSubject(ce.getContent());
		c.setUserId(user.getId().toString());
		c.setGoogleId(googleId);
		c.setTimeZone(zone.getRawOffset()/3600000);
		c.setStartTime(ce.getBeginDate());
		c.setEndTime(ce.getEndDate());
		c.setIsAllDayEvent(createEvent$ppallDay.isChecked() == true ? 1 : 0);
		c.setCategory(color);
		c.setCreateBy(user.getId().toString());
		c.setCreateDt(new Date());
		c.setUpdateBy(user.getId().toString());
		c.setUpdateDt(new Date());
		calendarService.addCalendar(c);
		
		ce.setTitle(googleId);
		cm.add(ce);
		
		createEvent$ppcnt.setRawValue("");
		createEvent$ppbt.setSelectedIndex(0);
		createEvent$ppet.setSelectedIndex(0);
		createEvent.setVisible(false);
		syncModel();
		
	}
	
	public void onClick$cancelBtn$createEvent(ForwardEvent event) {
		createEvent$ppcnt.setRawValue("");
		createEvent$ppbt.setSelectedIndex(0);
		createEvent$ppet.setSelectedIndex(0);
		createEvent.setVisible(false);
		((CalendarsEvent)createEvent.getAttribute("calevent")).clearGhost();
	}
	
	public void onEventEdit$calendars(ForwardEvent event) {
		CalendarsEvent evt = (CalendarsEvent) event.getOrigin();
		
		int left = evt.getX();
		int top = evt.getY();
		if (top + 245 > evt.getDesktopHeight())
			top = evt.getDesktopHeight() - 245;
		if (left + 410 > evt.getDesktopWidth())
			left = evt.getDesktopWidth() - 410;
		
		TimeZone tz = calendars.getDefaultTimeZone();
		
		editEvent.setLeft(left + "px");
		editEvent.setTop(top + "px");
		CalendarEvent ce = evt.getCalendarEvent();
		SimpleDateFormat edit_sdf = new SimpleDateFormat("HH:mm");
		edit_sdf.setTimeZone(tz);
		Calendar calendar = Calendar.getInstance(org.zkoss.util.Locales
				.getCurrent());
		String[] times = edit_sdf.format(ce.getBeginDate()).split(":");
		int hours = Integer.parseInt(times[0]);
		int mins = Integer.parseInt(times[1]);
		int bdTimeSum = hours + mins;
		editEvent$ppbt.setSelectedIndex(hours*12 + mins/5);
		times = edit_sdf.format(ce.getEndDate()).split(":");
		hours = Integer.parseInt(times[0]);
		mins = Integer.parseInt(times[1]);
		int edTimeSum = hours + mins;
		editEvent$ppet.setSelectedIndex(hours*12 + mins/5);
		boolean isAllday = (bdTimeSum + edTimeSum) == 0;
		editEvent$ppbegin.setTimeZone(tz);
		editEvent$ppbegin.setValue(ce.getBeginDate());
		editEvent$ppend.setTimeZone(tz);
		editEvent$ppend.setValue(ce.getEndDate());
		editEvent$ppallDay.setChecked(isAllday);
		editEvent$pplocked.setChecked(ce.isLocked());
		editEvent$ppbt.setVisible(!isAllday);
		editEvent$ppet.setVisible(!isAllday);
		editEvent$ppcnt.setValue(ce.getContent());
		String colors = ce.getHeaderColor() + "," + ce.getContentColor();
		int index = 0;
		if ("#3467CE,#668CD9".equals(colors))
			index = 1;
		else if ("#0D7813,#4CB052".equals(colors))
			index = 2;
		else if ("#88880E,#BFBF4D".equals(colors))
			index = 3;
		else if ("#7A367A,#B373B3".equals(colors))
			index = 4;
	
		switch (index) {
		case 0:
			editEvent$ppcolor.setStyle("color:#D96666;font-weight: bold;");
			break;
		case 1:
			editEvent$ppcolor.setStyle("color:#668CD9;font-weight: bold;");
			break;
		case 2:
			editEvent$ppcolor.setStyle("color:#4CB052;font-weight: bold;");
			break;
		case 3:
			editEvent$ppcolor.setStyle("color:#BFBF4D;font-weight: bold;");
			break;
		case 4:
			editEvent$ppcolor.setStyle("color:#B373B3;font-weight: bold;");
			break;
		}
		editEvent$ppcolor.setSelectedIndex(index);
		editEvent.setVisible(true);
	
		// store for the edit marco component.
		editEvent.setAttribute("ce", ce);
	}
	
	public void onClose$editEvent(ForwardEvent event) {
		event.getOrigin().stopPropagation();
		editEvent.setVisible(false);
	}
	
	public void onClick$okBtn$editEvent(ForwardEvent event) throws Exception {
		SimpleCalendarEvent ce = (SimpleCalendarEvent) editEvent.getAttribute("ce");
		Calendar cal = Calendar.getInstance(calendars.getDefaultTimeZone());
		Date beginDate = editEvent$ppbegin.getValue();
		Date endDate = editEvent$ppend.getValue();
		
		int bmin = 0;
		int emin = 0;
		if (!editEvent$ppallDay.isChecked()) {
			String[] times = editEvent$ppbt.getSelectedItem().getLabel().split(":");
			cal.setTime(beginDate);
			cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(times[0]));
			cal.set(Calendar.MINUTE, Integer.parseInt(times[1]));
			cal.set(Calendar.SECOND, 0);
			cal.set(Calendar.MILLISECOND, 0);
			beginDate = cal.getTime();
			times = editEvent$ppet.getSelectedItem().getLabel().split(":");
			cal.setTime(endDate);
			cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(times[0]));
			cal.set(Calendar.MINUTE, Integer.parseInt(times[1]));
			cal.set(Calendar.SECOND, 0);
			cal.set(Calendar.MILLISECOND, 0);
			endDate = cal.getTime();
		} else {
			cal.setTime(beginDate);
			cal.set(Calendar.HOUR_OF_DAY, 0);
			cal.set(Calendar.MINUTE, 0);
			cal.set(Calendar.SECOND, 0);
			cal.set(Calendar.MILLISECOND, 0);
			beginDate = cal.getTime();
			bmin = cal.get(Calendar.MINUTE);
			cal.setTime(endDate);
			cal.set(Calendar.HOUR_OF_DAY, 0);
			cal.set(Calendar.MINUTE, 0);
			cal.set(Calendar.SECOND, 0);
			cal.set(Calendar.MILLISECOND, 0);
			endDate = cal.getTime();
			emin = cal.get(Calendar.MINUTE);
		}			
		if (!beginDate.before(endDate)) {
			
			
			editEvent.setVisible(false);
			alert("The end date cannot be earlier than or equal to begin date!");
			((org.zkoss.calendar.event.CalendarsEvent)editEvent.getAttribute("calevent")).clearGhost();
			return;
		}
		if (bmin == 5 || bmin == 25 || bmin == 35 || bmin ==55) {
			editEvent.setVisible(false);
			alert("The begin minute:" + bmin + ", is not supported");
			((org.zkoss.calendar.event.CalendarsEvent)editEvent.getAttribute("calevent")).clearGhost();
			return;
		}
		if (emin == 5 || emin == 25 || emin == 35 || emin ==55) {
			editEvent.setVisible(false);
			alert("The end minute:" + emin + ", doesn't support");
			((org.zkoss.calendar.event.CalendarsEvent)editEvent.getAttribute("calevent")).clearGhost();
			return;
		}
		String[] colors = ((String)editEvent$ppcolor.getSelectedItem().getValue()).split(",");
		ce.setHeaderColor(colors[0]);
		ce.setContentColor(colors[1]);
		ce.setBeginDate(beginDate);
		ce.setEndDate(endDate);
		ce.setContent(editEvent$ppcnt.getValue());
		ce.setLocked(editEvent$pplocked.isChecked());
		
		UserBean user = (UserBean) Executions.getCurrent().getSession().getAttribute("loginUserInfo");
		HttpClient httpclient = new DefaultHttpClient();
		String url = CALENDAR_UPDATE.replace("#user", user.getLoginName()).replace("#eventId", ce.getTitle());
		HttpPut httpost = new HttpPut(url);
		httpost.addHeader("Content-Type", "application/json");
		httpost.addHeader("Authorization", "Bearer "+user.getPassword()+"");
		TimeZone zone = calendars.getDefaultTimeZone();
		JSONObject object = new JSONObject("{\"end\": {\"dateTime\": \""+DateUtils.getFormateDateStr(ce.getEndDate(), "yyyy-MM-dd'T'HH:mm:ss")+"\", \"timeZone\": \""+zone.getID()+"\"},\"start\": {\"dateTime\": \""+DateUtils.getFormateDateStr(ce.getBeginDate(), "yyyy-MM-dd'T'HH:mm:ss")+"\", \"timeZone\": \""+zone.getID()+"\"}}");
		String color = null;
		if ("#668CD9".equals(colors[1]))
			color = "9";
		else if ("#D96666".equals(colors[1]))
			color = "11";
		else if ("#4CB052".equals(colors[1]))
			color = "10";
		else if ("#B373B3".equals(colors[1]))
			color = "3";
		else
			color = "5";
		object.append("colorId", color);
		object.append("summary", ce.getContent());
		StringEntity myEntity = new StringEntity(object.toString());
		httpost.setEntity(myEntity);
		httpclient.execute(httpost);

		CalendarBean c = calendarService.getCalendarByGoogleId(ce.getTitle());
		c.setSubject(ce.getContent());
		c.setTimeZone(zone.getRawOffset()/3600000);
		c.setStartTime(ce.getBeginDate());
		c.setEndTime(ce.getEndDate());
		c.setIsAllDayEvent(createEvent$ppallDay.isChecked() == true ? 1 : 0);
		c.setCategory(color);
		c.setUpdateBy(user.getId().toString());
		c.setUpdateDt(new Date());
		calendarService.updateCalendar(c);
		
		cm.update(ce);
		editEvent.setVisible(false);
		syncModel();
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public void onClick$deleteBtn$editEvent(ForwardEvent event) throws InterruptedException {
		Messagebox.show("Are you sure to delete the event!", "Question",
				Messagebox.OK | Messagebox.CANCEL, Messagebox.QUESTION,
				new EventListener() {
					public void onEvent(Event evt) throws Exception {
						if (((Integer) evt.getData()).intValue() != Messagebox.OK)
							return;
						
						SimpleCalendarEvent sce = (SimpleCalendarEvent) editEvent.getAttribute("ce");
						calendarService.deleteCalendarByGoogleId(sce.getTitle());
						HttpClient httpclient = new DefaultHttpClient();
						UserBean user = (UserBean) Executions.getCurrent().getSession().getAttribute("loginUserInfo");
						String url = CALENDAR_DELETE.replace("#user", user.getLoginName()).replace("#eventId", sce.getTitle());
						HttpDelete httpdelete = new HttpDelete(url);
						httpdelete.addHeader("Content-Type", "text/xml");
						httpdelete.addHeader("Authorization", "Bearer "+user.getPassword()+"");
						httpclient.execute(httpdelete);
						cm.remove(sce);
						syncModel();
					}
				});
		editEvent.setVisible(false);
	}
	
	public void onEventUpdate$calendars(ForwardEvent event) throws Exception {
		CalendarsEvent evt = (CalendarsEvent) event.getOrigin();
		SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy/MM/d");
		sdf1.setTimeZone(calendars.getDefaultTimeZone());
		StringBuffer sb = new StringBuffer("Update... from ");
		sb.append(sdf1.format(evt.getCalendarEvent().getBeginDate()));
		sb.append(" to ");
		sb.append(sdf1.format(evt.getBeginDate()));
		popupLabel.setValue(sb.toString());
		int left = evt.getX();
		int top = evt.getY();
		if (top + 100 > evt.getDesktopHeight())
			top = evt.getDesktopHeight() - 100;
		if (left + 330 > evt.getDesktopWidth())
			left = evt.getDesktopWidth() - 330;
		updateMsg.open(left, top);
		timer.start();
		org.zkoss.calendar.Calendars cal = (org.zkoss.calendar.Calendars) evt
				.getTarget();
		SimpleCalendarModel m = (SimpleCalendarModel) cal.getModel();
		SimpleCalendarEvent sce = (SimpleCalendarEvent) evt.getCalendarEvent();
		sce.setBeginDate(evt.getBeginDate());
		sce.setEndDate(evt.getEndDate());
		
		UserBean user = (UserBean) Executions.getCurrent().getSession().getAttribute("loginUserInfo");
		CalendarBean c = calendarService.getCalendarByGoogleId(sce.getTitle());
		HttpClient httpclient = new DefaultHttpClient();
		String url = CALENDAR_UPDATE.replace("#user", user.getLoginName()).replace("#eventId", sce.getTitle());
		HttpPut httpost = new HttpPut(url);
		httpost.addHeader("Content-Type", "application/json");
		httpost.addHeader("Authorization", "Bearer "+user.getPassword()+"");
		TimeZone zone = calendars.getDefaultTimeZone();
		JSONObject object = new JSONObject("{\"end\": {\"dateTime\": \""+DateUtils.getFormateDateStr(sce.getEndDate(), "yyyy-MM-dd'T'HH:mm:ss")+"\", \"timeZone\": \""+zone.getID()+"\"},\"start\": {\"dateTime\": \""+DateUtils.getFormateDateStr(sce.getBeginDate(), "yyyy-MM-dd'T'HH:mm:ss")+"\", \"timeZone\": \""+zone.getID()+"\"}}");
		object.append("colorId", c.getCategory());
		object.append("summary", c.getSubject());
		StringEntity myEntity = new StringEntity(object.toString());
		httpost.setEntity(myEntity);
		httpclient.execute(httpost);

		c.setTimeZone(zone.getRawOffset()/3600000);
		c.setStartTime(sce.getBeginDate());
		c.setEndTime(sce.getEndDate());
		c.setUpdateBy(user.getId().toString());
		c.setUpdateDt(new Date());
		calendarService.updateCalendar(c);
		
		m.update(sce);
	}
	
	public void onMoveDate(ForwardEvent event) {
		if ("arrow-left".equals(event.getData()))
			calendars.previousPage();
		else calendars.nextPage();
		updateDateLabel();
		queryCalendarData();
		syncModel();
	}
	
	
	public void onWeekClick$calendars(ForwardEvent event) {
		Event evt = event.getOrigin();
		Date d = (Date) evt.getData();
		TimeZone tz = calendars.getDefaultTimeZone();
		Calendar cal = Calendar.getInstance(tz);
		cal.setTime(d);
	}
	
	
	public void onToday(ForwardEvent event) {
		calendars.setCurrentDate(Calendar.getInstance(calendars.getDefaultTimeZone()).getTime());
		updateDateLabel();
		syncModel();
	}
	
	public void onSwitchTimeZone(ForwardEvent event) {
		Map zone = calendars.getTimeZones();
		if (!zone.isEmpty()) {
			Map.Entry me = (Map.Entry) zone.entrySet().iterator().next();
			calendars.removeTimeZone((TimeZone) me.getKey());
			calendars.addTimeZone((String) me.getValue(), (TimeZone) me.getKey());
		}
		syncModel();
	}
	
	public void onUpdateFirstDayOfWeek(ForwardEvent event) {
		Listbox listbox = (Listbox) event.getOrigin().getTarget();
		calendars.setFirstDayOfWeek(listbox.getSelectedItem().getLabel());
		syncModel();
	}
	
	public void onUpdateView(ForwardEvent event) {
		String text = String.valueOf(event.getData());
		int days = "Day".equals(text) ? 1: "5 Days".equals(text) ? 5: "Week".equals(text) ? 7: 0;
		
		if (days > 0) {
			calendars.setMold("default");
			calendars.setDays(days);
		} else calendars.setMold("month");
		updateDateLabel();
		queryCalendarData();
		FDOW.setVisible("month".equals(calendars.getMold()) || calendars.getDays() == 7);
	}
	
	public void onClick$refreshCalendarData() throws Exception {
		UserBean user = (UserBean) Executions.getCurrent().getSession().getAttribute("loginUserInfo");
		List<CalendarBean> listgoogle = queryGoogleCalendarData(user);
		List<CalendarBean> list = calendarService.findCalendarsByUserId(user.getId());
		if (list != null && list.size() > 0) {
			list.removeAll(listgoogle);
			String[] ids = new String[list.size()];
			for (int i = 0; i < list.size(); i++) {
				CalendarBean c = list.get(i);
				ids[i] = c.getId().toString();
			}
			if (list != null && list.size() > 0) {
				calendarService.deleteCalendarBatch(ids);
			}
		}
		String[] str = new String[listgoogle.size()];
		if (listgoogle != null && listgoogle.size() > 0) {
			for (int i = 0; i < listgoogle.size(); i++) {
				CalendarBean c = listgoogle.get(i);
				str[i] = c.getGoogleId();
			}
			List<CalendarBean> tmpList = calendarService.findCalendarsByIds(str);
			calendarService.updateCalendarBatch(tmpList);
			listgoogle.removeAll(tmpList);
		}
		calendarService.addCalendarBatch(listgoogle);
		queryCalendarData();
	}
	
	private void queryCalendarData() {
		UserBean user = (UserBean) Executions.getCurrent().getSession().getAttribute("loginUserInfo");
		List<CalendarBean> list = calendarService.queryCalendars(calendars.getBeginDate(), calendars.getEndDate(), user.getId().toString());
		String[] color = new String[2];
		cm.clear();
		for (CalendarBean calendar : list) {
			SimpleCalendarEvent sce = new SimpleCalendarEvent();
			sce.setBeginDate(calendar.getStartTime());
			sce.setEndDate(calendar.getEndTime());
			color = renderColor(calendar.getCategory());
			sce.setHeaderColor(color[0]);
			sce.setContentColor(color[1]);
			// ce.setTitle() if any, otherwise, the time stamp is assumed.
			sce.setTitle(calendar.getGoogleId());
			sce.setContent(calendar.getSubject());
			cm.add(sce);
		}
	}
	
	private List<CalendarBean> queryGoogleCalendarData(UserBean user) throws Exception {
		List<CalendarBean> list = new ArrayList<CalendarBean>();
		try {
			HttpClient httpclient = new DefaultHttpClient();
			String url = GOOGLECALENDARURL.replace("#user", user.getLoginName()).replace("#password", user.getPassword());
			HttpGet httpget = new HttpGet(url);
			httpget.addHeader("Content-Type", "text/xml");
			HttpResponse response = httpclient.execute(httpget);
			HttpEntity resEntity = response.getEntity();
			InputStreamReader reader = new InputStreamReader(
					resEntity.getContent(), "UTF-8");
			char[] buff = new char[1024];
			StringBuffer sb = new StringBuffer();
			int length = 0;
			while ((length = reader.read(buff)) != -1) {
				sb.append(new String(buff, 0, length));
			}
			
			JSONObject jsonobject = new JSONObject(sb.toString());
			TimeZone now = TimeZone.getDefault();
			if (jsonobject.has("timeZone")) {
				now = TimeZone.getTimeZone((String) jsonobject.get("timeZone"));
			}
			int clientzone = now.getRawOffset()/3600000;
			Date start = new Date();
			Date end = new Date();
			int isAllDayEvent = 0;
			if (jsonobject.has("items")) {
				JSONArray array = jsonobject.getJSONArray("items");
				JSONObject object = null;
				CalendarBean c = new CalendarBean();
				for (int i = 0; i < array.length(); i++) {
					object = array.getJSONObject(i);
					if (object.has("id")) {
						c.setGoogleId(object.get("id").toString());
					}
					if (object.has("summary")) {
						c.setSubject(object.get("summary").toString());
					}
					if (object.has("location")) {
						c.setLocation(object.get("location").toString());
					}
					if (object.has("description")) {
						c.setDescription(object.get("description").toString());
					}
					if (object.has("colorId")) {
						c.setCategory(object.get("colorId").toString());
					}
					if (object.has("start")) {
						JSONObject startobj = object.getJSONObject("start");
						if (startobj.has("date")) {
							isAllDayEvent = 1;
							start = DateUtils.getFormateDate(startobj.get("date").toString(), "yyyy-MM-dd");
						} else if(startobj.has("dateTime")) {
							start = DateUtils.getFormateDate(startobj.get("dateTime").toString(), "yyyy-MM-dd'T'HH:mm:ss");
						}
						c.setStartTime(start);
					}
					if (object.has("end")) {
						JSONObject endobj = object.getJSONObject("end");
						if (endobj.has("date")) {
							end = start;
						} else if(endobj.has("dateTime")) {
							end = DateUtils.getFormateDate(endobj.get("dateTime").toString(), "yyyy-MM-dd'T'HH:mm:ss");
						}
						c.setEndTime(end);
					}
					c.setIsAllDayEvent(isAllDayEvent);
					c.setUserId(user.getId().toString());
					c.setTimeZone(clientzone);
					c.setCreateBy(user.getId().toString());
					c.setCreateDt(DateUtils.getFormateDate(object.get("created").toString(), "yyyy-MM-dd'T'HH:mm:ss"));
					c.setUpdateBy(user.getId().toString());
					c.setUpdateDt(DateUtils.getFormateDate(object.get("updated").toString(), "yyyy-MM-dd'T'HH:mm:ss"));
					list.add(c);
					c = new CalendarBean();
				}
			}
			return list;
		} catch(Exception e) {
			throw new Exception(e);
		}
		
	}
	
	private String[] renderColor(String category) {
		int index;
		if (StringUtils.isBlank(category))
			index = 9;
		else
			index = Integer.parseInt(category);
		String[] color = new String[2];
		switch (index) {
		case 11:
			color[0] = "#A32929";
			color[1] = "#D96666";
			break;
		case 9:
			color[0] = "#3467CE";
			color[1] = "#668CD9";
			break;
		case 3:
			color[0] = "#7A367A";
			color[1] = "#B373B3";
			break;
		case 5:
			color[0] = "#88880E";
			color[1] = "#BFBF4D";
			break;
		case 10:
			color[0] = "#0D7813";
			color[1] = "#4CB052";
			break;
		}
		return color;
	}

	public void setCalendarService(CalendarService calendarService) {
		this.calendarService = calendarService;
	}
	
}